#pragma once
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include "Log.hpp"
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

namespace kzz
{
    class UdpServer
    {
    public:
        UdpServer(std::string ip, uint16_t port)
            : _sockfd(-1), _port(port), _ip(ip), _isrunning(false)
        {
        }
        void Init()
        {
            //kzz::LOG(LogLevel::DBUGER0)
            //////////////气死我了，再犯这种智障错误我就是猪////////////////////////////////////////////////////
            //int  _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            /////////////////////////////////////////////////////////////////////////////////////////////////
              _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd < 0)
            {
                kzz::LOG(LogLevel::ERROR) << "server创建套接字失败";
                exit(1);
            }

            kzz::LOG(LogLevel::ERROR) << "server socket success,sockfd:" << _sockfd;
            // kzz::LOG(LogLevel::ERROR) <<_sockfd;
            //  std::cout << "创建套接字成功,文件描述符为：" << _sockfd << std::endl;

            // 定义socke地址结构体
            struct sockaddr_in local;
            // 清零
            bzero(&local, sizeof(local));
            // 区分是本地通信还是网络通信
            local.sin_family = AF_INET;
            // 端口号，把本地改成网络序列，
            // 在这等待某个IP下的某个端口
            local.sin_port = htons(8080);
            // IP转换成网络序列
            //   in_addr_t inet_addr(const char *cp);
            // 本机的IP，等待这个IP下的某个端口发来的信息
            //local.sin_addr.s_addr = inet_addr(_ip.c_str());
            //等代本机所有网卡的绑定端口
            local.sin_addr.s_addr=INADDR_ANY;
        
            //服务器需要其他客户端明确知道是哪一个端口，但是客户端不需要，
            // 把本sock固定在这个端口
 
            int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));

            if (n != 0)
            {
                kzz::LOG(LogLevel::ERROR) << "bind error";
                exit(1);
            }
            kzz::LOG(LogLevel::ERROR) << "bind success";
            
           
        }
       
        // 服务器接受数据，然后处理完发回去
        void Start()
        {
            _isrunning = true;
            while (_isrunning)
            {
                // 定义socke地址结构体,用来保存客户端的IP和端口号
                struct sockaddr_in client_addr;
                client_addr.sin_family=AF_INET;
                socklen_t len=sizeof(client_addr);
                //////////////////////////////////////////////////////////////
                char buffer[1024];
                ssize_t s=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&client_addr,&len);
                std::cout<<"from client,s:"<<s<<std::endl;
               if(s<0)
               {
                   kzz::LOG(LogLevel::DBUGER)<<"recvfrom fail";
                   exit(1);
               }
               if(s==0)
               std::cout<<s<<std::endl;
                if(s>0)
                {
                     std::string client_ip=inet_ntoa(client_addr.sin_addr);
                uint16_t client_port=ntohs(client_addr.sin_port);
                    kzz::LOG(LogLevel::DBUGER)<<"服务器收取数据成功,客户端为"<<client_ip.c_str()<<' '<<client_port
                    <<"数据为: "<<buffer;

                ///对收到的数据处理，然后传回
                buffer[0]='b';
                ssize_t n=sendto(_sockfd,buffer,sizeof(buffer),0,(struct sockaddr*)&client_addr,len);
                    if(n<0)
                    kzz::LOG(LogLevel::WORING)<<"server sendto fail !!!";

               }
               
            }
        }

    private:
        int _sockfd;
        uint16_t _port;
        std::string _ip;
        bool _isrunning;
    };
}